﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Diagnostics;
using System.Reflection;
using System.IO;

using FerrScript;
using FerrScript.Builder;

namespace FerrScriptTester
{
    class Program
    {
        static void Main(string[] args)
        {
            FerrScriptCompiler.Inst.OnRuntimeError += RuntimeException;

            TestScripts();
        }

        private static void TestScripts()
        {
            // set up script storing variables
            List<string>  scriptFiles = new List<string> ();
            List<FScript> scripts     = new List<FScript>();

            scriptFiles.Add("FieldsAndObjects.txt");
            scriptFiles.Add("ForLoopTest.txt");
            scriptFiles.Add("BasicArithmeticTest.txt");
            scriptFiles.Add("MethodCalls.txt");
            scriptFiles.Add("ScopeTest.txt");
            scriptFiles.Add("NoBodyTest.txt");
            scriptFiles.Add("FunctionTest.txt");

            FerrScriptCompiler.Inst.AddFunction("testFunction", typeof(TestClass), "DoSomethingStatic");

            // compile scripts and output errors
            for (int i = 0; i < scriptFiles.Count; i++)
            {
                // load and compile this script
                StreamReader reader = new StreamReader("Scripts\\" + scriptFiles[i]);
                FScript      script = FerrScriptCompiler.Inst.Compile(reader.ReadToEnd());

                // print errors
                if (FerrScriptCompiler.Inst.Errors.Count > 0 || script == null)
                {
                    Console.WriteLine(scriptFiles[i] + ", " + FerrScriptCompiler.Inst.Errors.Count + " errors");
                    for (int e = 0; e < FerrScriptCompiler.Inst.Errors.Count; e++)
                        Console.WriteLine(FerrScriptCompiler.Inst.Errors[e]);
                }

                // add it to the list
                if (script != null)
                    scripts.Add(script);
                else
                {
                    scriptFiles.RemoveAt(i);
                    i--;
                }
                reader.Close();
            }

            // execute scripts
            Stopwatch stopWatch = Stopwatch.StartNew();
            int collections = GC.CollectionCount(0);
            for (int t = 0; t < 1; t++)
                for (int i = 0; i < scripts.Count; i++)
                {
                    Console.WriteLine("____________________________");
                    Console.WriteLine("Script executing: " + scriptFiles[i] + "\n");

                    stopWatch.Reset();
                    stopWatch.Start();
                    ScriptValue sv = scripts[i].Run();
                    stopWatch.Stop();
                    Console.WriteLine("____________________________");
                    Console.WriteLine("Result: " + sv);
                    Console.WriteLine("Script elapsed time = " + (((float)stopWatch.ElapsedTicks / (float)Stopwatch.Frequency)) * 1000.0f + "ms\n\n\n");
                }

            Console.WriteLine("Collections: " + (GC.CollectionCount(0) - collections));

            FScript functionScript = FerrScriptCompiler.Inst.Compile(new StreamReader("Scripts\\FunctionTest.txt").ReadToEnd());
            ScriptValue factorialResult = functionScript.CallFunction("Factorial", new object[] { 5 });
            Console.WriteLine("Call to Factorial(5) = " + factorialResult);
        }

        public static void RuntimeException(string aExeptionText)
        {
            Console.WriteLine("Runtime Exception! - \n" + aExeptionText);
        }
    }
}
